package middlewares

import (
	"context"
	"os"

	"gitee.com/go-course/go12/devcloud-mini/maudit/apps/event"
	"github.com/emicklei/go-restful/v3"
	"github.com/infraboard/mcenter/apps/endpoint"
	"github.com/infraboard/mcenter/apps/token"
	"github.com/infraboard/mcube/ioc/config/application"
	ioc_kafka "github.com/infraboard/mcube/ioc/config/kafka"
	"github.com/infraboard/mcube/ioc/config/logger"
	"github.com/infraboard/mcube/tools/pretty"
	"github.com/rs/zerolog"
	"github.com/segmentio/kafka-go"
)

func NewAuditor() restful.FilterFunction {
	topic := os.Getenv("MAUDIT_EVENT_TOPIC")
	if topic == "" {
		topic = event.DEFAULT_TOPIC
	}

	return (&auditor{
		// 引入中间件后，通过配置环境变量接入
		w: ioc_kafka.Producer(topic),
		l: logger.Sub("auditor"),
	}).GoRestfulAuthFunc
}

// 用于接入审计中心的中间件
type auditor struct {
	// 集成kafka writer
	w *kafka.Writer
	l *zerolog.Logger
}

func (a *auditor) GoRestfulAuthFunc(
	req *restful.Request,
	resp *restful.Response,
	next *restful.FilterChain) {

	//  从路由当做获取
	// 请求拦截, 权限检查
	entry := endpoint.NewEntryFromRestRequest(req)

	// 由于审计有性能开销
	// 开启认证
	// Metadata(label.Auth, label.Enable).
	// 开启审计
	// Metadata(label.Audit, label.Enable).

	if entry.AuthEnable && entry.AuditLog {
		// 从认证中间件后， 取消认证后的上下文
		obj := req.Attribute(token.TOKEN_ATTRIBUTE_NAME)
		if obj == nil {
			return
		}
		tk := obj.(*token.Token)

		event := &event.OperateEventData{
			UserName:     tk.Username,
			ServiceName:  application.App().AppName,
			ResourceType: entry.Resource,
			Action:       entry.Labels["action"],
			FeaturePath:  entry.Path,
			Request:      pretty.ToJSON(req.Request),
			Response:     "{}",
		}
		err := a.w.WriteMessages(context.Background(),
			kafka.Message{
				Value: []byte(pretty.ToJSON(event)),
			},
		)
		if err != nil {
			a.l.Error().Msgf("write audit log error, %s", err)
		}
	}

	// next
	next.ProcessFilter(req, resp)
}
